Repository navigation
Do not recurse when getting the metadata of an NWB file in a BIDS dataset - #1958
CodyCBakerPhD wants to merge 2 commits into
Conversation
…aset For an NWB file in a BIDS dataset, get_metadata() took the BIDS metadata from NWBBIDSAsset.get_metadata(), which also extracts the NWB metadata by calling nwb2asset() and thus get_metadata() again, and so on until RecursionError: ~100 levels, each running the BIDS validator. The result was still correct, as each level falls back on errors, but it took about a minute per file (and timed out CI on Windows). Take only the BIDS metadata, with BIDSAsset.get_metadata(). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qn5WBSiQgoZoL4fytF6nEr
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #1958 +/- ##
==========================================
+ Coverage 90.77% 90.82% +0.05%
==========================================
Files 92 92
Lines 14130 14159 +29
==========================================
+ Hits 12826 12860 +34
+ Misses 1304 1299 -5
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
@yarikoptic this one was discovered back in the bids-dandisets days but fixing was delayed until closer to 'eventual' BEP032 integration Might as well do it now though, with all the other validation improvements going on |
| # Only the BIDS metadata: `df` is an `NWBBIDSAsset`, whose own | ||
| # `get_metadata()` would extract the NWB metadata by calling this | ||
| # function again, recursing until `RecursionError` | ||
| path_metadata = bids.BIDSAsset.get_metadata(df, digest=digest) |
There was a problem hiding this comment.
but this sounds like a band-aid if there is some infinite recursion -- shouldn't it be fixed where it happens to prevent generally -- would that be possible here?
There was a problem hiding this comment.
Sure, the first version was bare-bones minimal code to do the job, but the current version is more direct to the source of the problem (not disambiguating between BIDS and non-BIDS metadata calls), which is now split
… asset Getting the metadata of an NWB file in a BIDS dataset recursed because of a cycle between two methods that each merge BIDS and NWB metadata: `NWBBIDSAsset.get_metadata()` extracts the NWB metadata with `dandi.metadata.nwb.get_metadata()`, which itself got the BIDS metadata of the file with `get_metadata()` of its `NWBBIDSAsset`. Calling `BIDSAsset.get_metadata()` unbound only patched this one call site. Instead, give BIDS assets a method returning only their BIDS metadata, which no subclass overrides to read the content, and use it wherever only the BIDS metadata is wanted: when extracting the metadata of an NWB file, and in `NWBBIDSAsset.get_metadata()` and `ZarrBIDSAsset.get_metadata()` (no change in behavior). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Qn5WBSiQgoZoL4fytF6nEr
Problem
For an NWB file in a BIDS dataset,
dandi.metadata.nwb.get_metadata()took the BIDS part of the metadata fromdf.get_metadata().dfis anNWBBIDSAsset, and itsget_metadata()also extracts the NWB metadata, viaNWBAsset.get_metadata()→nwb2asset()→get_metadata(). That calls back into the same BIDS branch, so the cycle repeats untilRecursionError.The result was still correct, because
NWBAsset.get_metadata()falls back to default metadata on errors at each level. But the BIDS validator ran at every one of roughly 100 levels. Onieeg_epilepsyNWBfrom bids-examples, oneget_metadata()call made 98 nestednwb2asset()calls and took about 60 s. That is what madetest_bids_nwb_metadata_integrationtime out on Windows CI.Fix
Take only the BIDS metadata, via
bids.BIDSAsset.get_metadata(df, ...), which was the intent of that branch. The NWB metadata is extracted by the rest ofget_metadata()itself.Measured on the same file:
nwb2asset()callssubject_id/sex01/U01/U🤖 Generated with Claude Code
https://claude.ai/code/session_01Qn5WBSiQgoZoL4fytF6nEr